﻿/*
 * KLF Headless Browser
 * Written by Kris Oye <kristianoye@gmail.com>
 * Copyright (C) 2011-2012.  All rights reserved.
 */
namespace KLF.Lib.Browser.DOM.HTML
{
    #region Using Statements

    using System.Linq;
    using System.Collections.Generic;
    using Jint;

    #endregion

    public class HTMLCollection : IPropertyGetter
    {
        #region Properties

        internal Node[] _Nodes { get; set; }

        internal List<Node> Nodes { get { return new List<Node>(_Nodes); } }

        internal Document Source { get; set; }

        #endregion

        #region Constructors

        internal HTMLCollection(Document source, IEnumerable<Node> _nodes)
        {
            _Nodes = _nodes.ToArray();
            Source = source;
        }

        #endregion

        #region DOM Level 2 HTML Compliance

        /// <summary>
        /// Enables this object to act as an array.  Exactly the same as 
        /// calling list.item(index).
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public object this[int index]
        {
            get
            {
                if (index > -1 && index < _Nodes.Length)
                    return item(index);
                else
                    return null;
            }
        }

        /// <summary>
        /// Shortcut for this.namedItem( byName );
        /// </summary>
        /// <param name="byName"></param>
        /// <returns></returns>
        public object this[string byName]
        {
            get
            {
                return namedItem(byName);
            }
            set
            {
                var o = value;
            }
        }

        /// <summary>
        /// This method retrieves a node specified by ordinal index. Nodes are
        /// numbered in tree order (depth-first traversal order). 
        /// </summary>
        /// 
        /// <param name="index">The index of the node to be fetched. The index origin is 0</param>
        /// 
        /// <returns>The Node at the corresponding position upon success. A 
        /// value of null is returned if the index is out of range.</returns>
        public Node item(int index)
        {
            if (index > -1 && index < _Nodes.Length)
            {
                return _Nodes[index];
            }
            return null;
        }

        /// <summary>
        /// This attribute specifies the length or size of the list.
        /// </summary>
        public int length { get { return _Nodes.Length; } }

        /// <summary>
        /// This method retrieves a Node using a name. With [HTML 4.01] 
        /// documents, it first searches for a Node with a matching id 
        /// attribute. If it doesn't find one, it then searches for a Node
        /// with a matching name attribute, but only on those elements that
        /// are allowed a name attribute. With [XHTML 1.0] documents, this
        /// method only searches for Nodes with a matching id attribute. 
        /// This method is case insensitive in HTML documents and case 
        /// sensitive in XHTML documents. 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Node namedItem(string name)
        {
            var result = Nodes
                .DefaultIfEmpty(null)
                .FirstOrDefault(e =>
                    {
                        HTMLElement he = e as HTMLElement;
                        return (he != null && 
                            he.eqAttribute(
                                HTMLConstants.HTML_ATT_ID, 
                                name, 
                                (Source is XHTMLDocument)));
                    });

            if (result == null)
            {
                result = Nodes
                    .DefaultIfEmpty(null)
                    .FirstOrDefault(e =>
                        {
                            HTMLElement he = e as HTMLElement;
                            return (he != null && 
                                he.eqAttribute(
                                    HTMLConstants.HTML_ATT_NAME, 
                                    name, 
                                    (Source is XHTMLDocument)));
                        });
            }
            return result;
        }

        #endregion

        #region IPropertyGetter Members

        public bool TryGetProperty(string index, out Jint.Native.JsInstance result)
        {
            throw new System.NotImplementedException();
        }

        #endregion
    }
}
